ident = '$Id: dav_ui.py 104 2006-05-25 22:06:43Z ahmad $'

import wx, wx.gizmos, rex, common, images, re, davs, os, os.path
import rex.dav
from xml.dom	 import minidom

# Sort BY and Find By
BY_NAME		= 1
BY_ISS_ID	= 0
BY_ISS_NAME = 1
BY_PUB_ID	= 2
BY_PUB_NAME = 3

# Menu bar items
ID_SORTBY		= 101
ID_FINDBY		= 102
ID_FINDBY_TEXT	= 103

ID_DISCONNECT		= 105
ID_RELOAD			= 106

ID_DIR_CREATE		= 111
ID_DIR_EDIT			= 112
ID_DIR_DELETE		= 113
ID_DIR_UPLOAD		= 114
ID_DIR_CLONE		= 115
ID_DIR_COPY			= 116

ID_FIL_EDIT			= 121
ID_FIL_DELETE		= 122
ID_FIL_DOWNLOAD		= 123
ID_FIL_CREATE		= 124
ID_FIL_COPY			= 125
ID_FIL_UPLOAD		= 126

ID_DAV_RENAME		= 131

class dav_tree( wx.gizmos.TreeListCtrl ):
	def __init__( self, parent, id=-1 , style=0 ):
		wx.gizmos.TreeListCtrl.__init__( self, parent, id , style=style)
		self.sortby = BY_NAME
		self.ascending = 1
		if wx.Platform == '__WXMAC__':
			font = self.GetMainWindow().GetFont()
			font.SetPointSize( 10 )
			self.GetMainWindow().SetFont( font )
			font = self.GetHeaderWindow().GetFont()
			font.SetPointSize( 10 )
			self.GetHeaderWindow().SetFont( font )
		
	def OnCompareItems( self, item1, item2 ):
		t1 = self.GetPyData( item1 )
		t2 = self.GetPyData( item2 )
		if ( t1 is None ) or ( t2 is None ): return 0
		# compare by type
		v1 = t1["type"]
		v2 = t2["type"]
		if v1 == v2:
			# same type, compare by name
			v1 = t1["name"].lower()
			v2 = t2["name"].lower()
			if v1 < v2:
				return -1
			else:
				return 1
		else:
			if v1 == 'dir':
				return -1
			else:
				return 1

class dav_control( wx.Panel ):
	def __init__( self, parent, id, account ):
		wx.Panel.__init__( self, parent, id )
		self.parent	= parent
		self.account= account
		self.davCon	= rex.dav.dav_connection( account, account.username, account.password )
		self.last_objects_found	= []
		# Create the menu bar
		self.create_menu_items()
		# Create the list control and set it's image list
		tID = wx.NewId()
		self.tree = dav_tree( self, tID, style=wx.TR_DEFAULT_STYLE | wx.TR_FULL_ROW_HIGHLIGHT )
		self.tree.AddColumn( "name" )
		self.tree.AddColumn( "size" )
		self.tree.AddColumn( "modified" )
		self.tree.SetMainColumn(0)
		isz = (16,16)
		self.il = wx.ImageList(isz[0], isz[1])
		self.folder_icon		= self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER,      wx.ART_OTHER, isz))
		self.folder_open_icon	= self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN,   wx.ART_OTHER, isz))
		self.file_icon			= self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz))
		new_folder_bitmap = None
		new_folder_bitmap = images.getNewFolderWBitmap()
		self.tree.SetImageList( self.il )
		self.tree.SetColumnWidth( 0, 200 )
		self.tree.SetColumnWidth( 1, 70 )
		self.tree.SetColumnWidth( 2, 100 )
		self.tree.GetMainWindow().Bind( wx.EVT_LEFT_DCLICK, self.OnItemDoubleClick )
		self.tree.GetMainWindow().Bind( wx.EVT_RIGHT_DOWN, self.OnTreeRightClick )
		self.tree.GetMainWindow().Bind( wx.EVT_LEFT_DOWN, self.OnTreeLeftClick )
		self.tree.Bind( wx.EVT_TREE_ITEM_EXPANDED, self.OnFolderExpanded, id=tID )
		# create a dav item for the root
		davItem = rex.dav.dav_item()
		davItem.name = '/'
		davItem.uri  = '/'
		davItem.type = 'dir'
		self.root = self.tree.AddRoot( davItem.name )
		self.tree.SetItemImage( self.root, self.folder_icon, which = wx.TreeItemIcon_Normal )
		self.tree.SetItemImage( self.root, self.folder_icon, which = wx.TreeItemIcon_Expanded )
		self.tree.SetPyData( self.root, davItem )
		self.tree.SetItemHasChildren( self.root, True )
		self.tree.Bind( wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag, id=tID )
		self.topbar = wx.BoxSizer( wx.HORIZONTAL )
		# The new button
		self.new_button = wx.BitmapButton( self, -1, new_folder_bitmap, size=common.button_size, style=wx.NO_BORDER )
		self.new_button.Bind( wx.EVT_BUTTON, self.OnFolderCreate )
		self.topbar.Add( self.new_button, 0 )
		# The refresh button
		self.refresh_button = wx.BitmapButton( self, -1, images.getRefreshBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.refresh_button.Bind( wx.EVT_BUTTON, self.reload_folder )
		self.topbar.Add( self.refresh_button, 0 )
		# expanded space
		self.space = wx.Panel( self, -1)
		self.topbar.Add( self.space, 2, wx.EXPAND )
		# zoom button
		self.zoom_button = wx.BitmapButton( self, -1, images.getZoomBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.zoom_button.Bind( wx.EVT_BUTTON, self.OnZoom )
		self.topbar.Add( self.zoom_button, 0 )
		# The whole mess
		self.sizer = wx.BoxSizer( wx.VERTICAL )
		self.sizer.Add( self.topbar, 0, wx.EXPAND )
		self.sizer.Add( self.tree, 1, wx.EXPAND )
		self.SetSizer( self.sizer )
		self.SetAutoLayout( 1 )
		# Windows needs this call
		self.Layout()
		self.Show()
		self.tree.Refresh()

	def OnBeginDrag( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		obj = self.tree.GetPyData( item )
		if obj is None: return
		data = wx.PyTextDataObject()
		data.SetText( obj.uri )
		ds = wx.DropSource( self )
		ds.SetData( data )
		result = ds.DoDragDrop()

	def create_menu_items( self ):
		self.menubar = self.account.window.menubar
		# The nothing menu
		menu = wx.Menu()
		menu.Append( ID_RELOAD, "&Reload\tCtrl+R", " Reload" )
		menu.AppendSeparator()
		menu.Append( ID_FIL_DOWNLOAD, "&Download", " Download the selected folder" )
		menu.Append( ID_FIL_UPLOAD, "&Upload Files", " Upload files" )
		menu.Append( ID_DIR_UPLOAD, "&Upload Folder", " Upload folder" )
		menu.AppendSeparator()
		menu.Append( ID_FIL_CREATE, "&Create a New File", " Create a new file" )
		menu.Append( ID_DIR_CREATE, "&Create a New Folder", " Create a new folder" )
		self.none_menu = menu
		# The folder menu
		menu = wx.Menu()
		menu.Append( ID_RELOAD, "&Reload\tCtrl+R", " Reload" )
		menu.Append( ID_FIL_DOWNLOAD, "&Download", " Download the selected folder" )
		menu.Append( ID_FIL_UPLOAD, "&Upload Files", " Upload files to this folder" )
		menu.Append( ID_DIR_UPLOAD, "&Upload Folder", " Upload folder to this folders" )
		menu.AppendSeparator()
		menu.Append( ID_FIL_CREATE, "&Create a New File", " Create a new file" )
		menu.Append( ID_DIR_CREATE, "&Create a New Folder", " Create a new folder here" )
		menu.AppendSeparator()
		menu.Append( ID_DAV_RENAME, "&Rename", " Rename the selected folder" )
		menu.Append( ID_DIR_DELETE, "&Delete", " Delete the selected folder" )
		self.dir_menu = menu
		# The file menu
		menu = wx.Menu()
		menu.Append( ID_FIL_EDIT, "&Edit", " Edit the selected files" )
		menu.Append( ID_FIL_DOWNLOAD, "&Download", " Download the selected files" )
		menu.Append( ID_FIL_COPY, "&Copy URL Path", " Copy the selected file's URL path to the clipboard" )
		menu.AppendSeparator()
		menu.Append( ID_DAV_RENAME, "&Rename", " Rename the selected file" )
		menu.Append( ID_FIL_DELETE, "&Delete", " Delete the selected files" )
		# events
		self.Bind( wx.EVT_MENU, self.reload_folder	, id=ID_RELOAD		)
		self.Bind( wx.EVT_MENU, self.OnFolderCreate	, id=ID_DIR_CREATE	)
		self.Bind( wx.EVT_MENU, self.OnFolderEdit	, id=ID_DIR_EDIT	)
		self.Bind( wx.EVT_MENU, self.OnFolderDelete	, id=ID_DIR_DELETE	)
		self.Bind( wx.EVT_MENU, self.OnFolderUpload	, id=ID_DIR_UPLOAD	)
		self.Bind( wx.EVT_MENU, self.OnFileCreate	, id=ID_FIL_CREATE	)
		self.Bind( wx.EVT_MENU, self.OnFileEdit		, id=ID_FIL_EDIT	)
		self.Bind( wx.EVT_MENU, self.OnFileCopy		, id=ID_FIL_COPY	)
		self.Bind( wx.EVT_MENU, self.OnFileDelete	, id=ID_FIL_DELETE	)
		self.Bind( wx.EVT_MENU, self.OnFileDownload	, id=ID_FIL_DOWNLOAD)
		self.Bind( wx.EVT_MENU, self.OnFileUpload	, id=ID_FIL_UPLOAD	)
		self.Bind( wx.EVT_MENU, self.OnRename		, id=ID_DAV_RENAME	)
		self.fil_menu = menu
		
	def OnZoom( self, event ):
		if self.account.window: self.account.window.OnZoom( 2 )

	def AppendFolder( self, parent_folder_item, folder ):
		folder_item = self.tree.AppendItem( parent_folder_item, folder["name"] )
		self.tree.SetItemText( folder_item, folder["size"], 1 )
		self.tree.SetItemImage( folder_item, self.folder_icon, which = wx.TreeItemIcon_Normal )
		self.tree.SetItemImage( folder_item, self.folder_icon, which = wx.TreeItemIcon_Expanded )
		self.tree.SetItemText( folder_item, folder["mdate"], 2 )
		self.tree.SetPyData( folder_item, folder )
		self.tree.SetItemHasChildren( folder_item, True )
		return folder_item

	def AppendFile( self, parent_folder_item, fil ):
		fil_item = self.tree.AppendItem( parent_folder_item, fil["name"] )
		self.tree.SetItemText( fil_item, fil["size"], 1 )
		self.tree.SetItemText( fil_item, fil["mdate"], 2 )
		self.tree.SetItemImage( fil_item, self.file_icon, which = wx.TreeItemIcon_Normal )
		self.tree.SetItemImage( fil_item, self.file_icon, which = wx.TreeItemIcon_Selected )
		self.tree.SetPyData( fil_item, fil )
		return fil_item

	def OnFolderExpanded( self, event ):
		self.reload_folder( folder_item = event.GetItem() )

	def get_dav_item_path( self, folder_item ):
		if not folder_item:
			common.dprint("No folder item, ")
			return '/'
		if folder_item == self.root:
			common.dprint("The folder item is root")
			return '/'
		path = ''
		current_folder_item = folder_item
		while current_folder_item != self.root:
			davItem = self.tree.GetPyData( current_folder_item )
			folder_name = davItem['name']
			common.dprint("Folder name ", folder_name )
			path = "%s/%s" % ( folder_name, path )
			current_folder_item = self.tree.GetItemParent( current_folder_item )
		path = "/%s" % path
		if not self.tree.ItemHasChildren( folder_item ):
			path = path[:-1]
		return path
		
	def reload_folder( self, event=None, folder_item=None ):
		# Close off all open child frames
		if not folder_item:
			folder_item = self.root
		if self.account.window: self.account.window.SetStatusText( "Refreshing folder..." )
		wx.Yield()
		# Clear out the current tree items
		self.tree.DeleteChildren( folder_item )
		self.tree.SetItemHasChildren( folder_item )
		# Get the files
		dirFiles = None
		dirDirs = None
		path = self.get_dav_item_path( folder_item )
		common.dprint("Reloading DAV %s", path )
		try:
			cur = wx.BusyCursor()
			(dirDirs, dirFiles) = self.davCon.get_dav_items( path )
		except:
			common.show_error("Failed to load WebDAV folders")
		del cur
		for dirDir in dirDirs:
			new_folder_item = self.AppendFolder( folder_item, dirDir )
		for dirFile in dirFiles:
			fil_item = self.AppendFile( folder_item, dirFile )
		self.tree.SortChildren( folder_item )
		self.tree.Refresh()
		if self.account.window: self.account.window.SetStatusText( "Ready" )

	def OnClose( self, event ):
		'''When closing the service frame, the account manager icon is updated and the
		service reference is cleared out.
		If the account manager's disconnect_account method returns a false, the closing is
		not performed.'''
		# Close off all child frames
		if not self.CloseAllFrames(): return
		# Decrement the binder sui ref count
		da = self.GetParent().disconnect_account
		if da( self.account.account_manager_aid ) == 1:
			bf = self.account.binder_frame
			bf.ref_count = bf.ref_count -1
			bf.Close()
			cf = self.account.contact_frame
			cf.ref_count = cf.ref_count -1
			cf.Close()
			event.Skip()
			return True
		return False

	def OnDisconnect( self, event ):
		if self.OnClose( event ):
			self.Destroy()
			
	def OnRename( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		davItem = self.tree.GetPyData( item )
		# get the name
		dlg = wx.TextEntryDialog( self, 'Enter a new name', 'Rename', davItem.name )
		res = dlg.ShowModal()
		new_name = dlg.GetValue().strip()
		if ( res != wx.ID_OK ) or ( new_name == '' ):
			common.dprint("Canceling ", new_name )
			dlg.Destroy()
			return
		dlg.Destroy()
		# create the new and old uris
		olduri		= davItem.uri
		parentpath	= olduri
		if davItem.type == 'dir':
			# remove the trailing /
			parentpath = parentpath[:-1]
		# get the parent path
		parentpath = os.path.dirname( parentpath )
		if parentpath != '/':
			parentpath = parentpath + '/'
		# create the new uri
		newuri = parentpath + new_name
		if davItem.type == 'dir':
			# add the trailing /
			newuri = newuri + '/'
		if not self.davCon.rename_item( olduri, newuri ):
			common.show_error( "Failed to rename %s to %s" %(olduri, newuri) )
			return
		# rename the tree item
		davItem.name = new_name
		davItem.uri = newuri
		self.tree.SetItemText( item, davItem.name, 0 )
		if davItem.type == 'dir':
			self.tree.SortChildren( item )
		self.tree.SelectItem( item )
		
	def OnFolderCreate( self, event ):
		dirItem = self.tree.GetSelection()
		if dirItem is None: return
		davDir = self.tree.GetPyData( dirItem )
		# get the name
		dlg = wx.TextEntryDialog( self, 'Enter the new folder name', 'Create New Folder', '')
		res = dlg.ShowModal()
		folder_name = dlg.GetValue().strip()
		if ( res != wx.ID_OK ) or ( folder_name == '' ):
			common.dprint("Canceling ", folder_name )
			dlg.Destroy()
			return
		dlg.Destroy()
		newDavDir = self.davCon.create_dir( davDir.uri, folder_name )
		if not newDavDir:
			common.show_error( "Failed to create new folder" )
			return
		newDirItem = self.AppendFolder( dirItem, newDavDir )
		self.tree.SortChildren( dirItem )
		self.tree.SelectItem( newDirItem )

	def OnFolderEdit( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		pub = self.tree.GetPyData( item )
		if pub is None: return
		if pub.object_name != "publication": return
		if pub.editor is not None:
			# switch to this page
			try: self.account.window.ebook.SetSelection( common.get_page_index( self.account.window.ebook, pub.editor ) )
			except: common.dprint("Failed to switch to editor")
			return
		pub.editor = publications.publication( self.account, pub, item )
		# add the page
		self.account.window.ebook.AddPage( pub.editor, pub.editor.get_label_text() )
		pi = common.get_page_index( self.account.window.ebook, pub.editor )
		try:
			self.account.window.ebook.SetSelection( pi )
			self.account.window.ebook.SetPageImage( pi, self.account.window.icon_from_rex_object( pub ) )
		except:
			common.show_error("Failed to switch to editor", False)

	def OnFolderDelete( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		folder = self.tree.GetPyData( item )
		if folder is None: return
		# Confirm delete
		dconf = "Are you sure you want to delete this folder ?\n\t%s" % folder.uri
		res = wx.MessageBox( dconf, "Confirm Delete", wx.YES_NO )
		if res != wx.YES: return
		if not self.davCon.delete_item( folder.uri ):
			common.show_error("Failed to delete %s" % folder.uri )
			return
		parentItem = self.tree.GetItemParent( item )
		self.tree.Delete( item )
		self.tree.SelectItem( parentItem )
			
	def OnFolderUpload( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		davDir = self.tree.GetPyData( item )
		# select the folder to upload
		dlg = wx.DirDialog(self, "Select Floder to Upload", style=wx.DD_DEFAULT_STYLE )
		dlg.SetMessage( "Select Floder to Upload" )
		upload_path = ''
		if dlg.ShowModal() == wx.ID_OK:
			upload_path = dlg.GetPath()
		else:
			return
		dlg.Destroy()
		if not self.davCon.upload( upload_path, davDir.uri ):
			common.show_error("Error while uploading %s" % upload_path )
			return
		# otherwise reload the parent folder
		self.reload_folder( folder_item = item )

	def OnFileUpload( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		davDir = self.tree.GetPyData( item )
		# select the folder to upload
		dlg = wx.FileDialog(self, "Select Files to Upload", style=wx.OPEN | wx.MULTIPLE )
		dlg.SetMessage( "Select Files to Upload" )
		upload_files = []
		if dlg.ShowModal() == wx.ID_OK:
			upload_files = dlg.GetPaths()
		else:
			return
		dlg.Destroy()
		for upload_path in upload_files:
			if not self.davCon.upload( upload_path, davDir.uri ):
				common.show_error("Error while uploading %s" % upload_path )
				return
		# otherwise reload the parent folder
		self.reload_folder( folder_item = item )

	def OnFileCreate( self, event ):
		dirItem = self.tree.GetSelection()
		if dirItem is None: return
		davDir = self.tree.GetPyData( dirItem )
		# get the name
		dlg = wx.TextEntryDialog( self, 'Enter the new file name', 'Create a New File', '')
		res = dlg.ShowModal()
		file_name = dlg.GetValue().strip()
		if ( res != wx.ID_OK ) or ( file_name == '' ):
			common.dprint("Canceling ", file_name )
			dlg.Destroy()
			return
		dlg.Destroy()
		uri = os.path.join( davDir.uri, file_name )
		if not self.davCon.put_file( uri, '' ):
			common.show_error( "Failed to create new file %s" % uri )
			return
		davItem = rex.dav.dav_item()
		davItem.name = file_name
		davItem.uri  = uri
		davItem.size = '0 B'
		newFilItem = self.AppendFile( dirItem, davItem )
		self.tree.SortChildren( dirItem )
		self.tree.SelectItem( newFilItem )
		self.OnFileEdit( None )
		
	def OnFileCopy( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		fil = self.tree.GetPyData( item )
		if fil is None: return
		obj = fil['uri']
		# Now let's put it in the clipboard
		clipdata = wx.TextDataObject()
		clipdata.SetText( obj )
		wx.TheClipboard.Open()
		wx.TheClipboard.SetData( clipdata )
		wx.TheClipboard.Close()

	def OnFileEdit( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		fil = self.tree.GetPyData( item )
		if fil is None: return
		if fil['type'] != 'file': return
		fil_editor = common.find_dav_editor( self.account.window.ebook, fil )
		if fil_editor:
			# switch to this page
			try: self.account.window.ebook.SetSelection( common.get_page_index( self.account.window.ebook, fil_editor ) )
			except: common.show_error("Failed to switch to editor 1")
			return
		# is it a known text file type?
		ext = os.path.splitext( fil.uri )[1].replace('.','').lower()
		if ( ext != 'htaccess' ) and ( not ext in common.dav_text_types ):
			if ext in common.dav_image_types:
				self.OnFileDownload( None )
				return
			# Ask what to do
			msg = "The file extension .%s is not a known Text format.\nWhat would you like to do?" % ext
			sel_edit = 'Edit in the Text editor anyway'
			sel_download = 'Download to my Computer'
			dlg = wx.SingleChoiceDialog( self, msg, 'Non-Text file extension', [sel_edit, sel_download],  wx.CHOICEDLG_STYLE )
			res = dlg.ShowModal()
			selection = dlg.GetStringSelection()
			dlg.Destroy()
			if res == wx.ID_OK:
				if selection == sel_download:
					self.OnFileDownload( None )
					return
				elif selection == sel_edit:
					pass
				else:
					return
			else:
				return
		# no editor, download a fresh copy
		body = self.davCon.get_file( fil['uri'] )
		fil.data[0]['value'] = body
		fil_editor = davs.html( self.davCon, self.account, fil, item )
		# add the page
		self.account.window.ebook.AddPage( fil_editor, fil_editor.get_label_text() )
		pi = common.get_page_index( self.account.window.ebook, fil_editor )
		try:
			self.account.window.ebook.SetSelection( pi )
			self.account.window.ebook.SetPageImage( pi, self.account.window.icon_from_dav_object( fil ) )
		except:
			common.show_error("Failed to switch to editor 2", False)

	def OnFileDelete( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		fil = self.tree.GetPyData( item )
		if fil is None: return
		# Confirm delete
		dconf = "Are you sure you want to delete this file ?\n\t%s" % fil.uri
		res = wx.MessageBox( dconf, "Confirm Delete", wx.YES_NO )
		if res != wx.YES: return
		if not self.davCon.delete_item( fil.uri ):
			common.show_error("Failed to delete %s" % fil.uri )
			return
		parentItem = self.tree.GetItemParent( item )
		self.tree.Delete( item )
		self.tree.SelectItem( parentItem )

	def OnFileDownload( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		fil = self.tree.GetPyData( item )
		if fil is None: return
		# select the location
		dlg = wx.DirDialog(self, "Download to Folder", style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON)
		dlg.SetMessage( "Download to Folder" )
		download_path = ''
		if dlg.ShowModal() == wx.ID_OK:
			download_path = dlg.GetPath()
		else:
			return
		dlg.Destroy()
		# download
		self.davCon.download( fil, download_path )

	def OnTreeLeftClick( self, event ):
		self.tree.Refresh()
		event.Skip()

	def OnTreeRightClick( self, event ):
		item, where, column = self.tree.HitTest( event.GetPosition() )
		if item is None: return
		self.tree.SelectItem( item )
		object = None
		try: object = self.tree.GetPyData( item )
		except: pass
		if ( item == self.root ) or ( object is None ):
			self.PopupMenu( self.none_menu, wx.Point( event.m_x + 5, event.m_y + 15) )
			return
		menu = None
		if object['type'] == "dir":
			menu = self.dir_menu
		elif object['type'] == "file":
			menu = self.fil_menu
		if menu is None: return
		self.tree.EnsureVisible( item )
		self.tree.SelectItem( item )
		self.PopupMenu( menu, wx.Point( event.m_x + 5, event.m_y + 15) )

	def OnItemDoubleClick( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		path = self.get_dav_item_path( item )
		common.dprint("DBLClick: ", path )
		davItem = self.tree.GetPyData( item )
		if davItem is None: return
		if davItem['type'] == "file":
			self.OnFileEdit( event )

	def SetTextOfItem( self, item, text ):
		self.tree.SetItemText( item, text )

	def CloseAllFrames( self ):
		'''Cycle through all publications and issues and close off their frames if any.'''
		for p in self.publications:
			if p.editor is not None:
				f = p.editor
				if f.OnClose( None ):
					f.Destroy()
				else:
					return False
			# Check it's child publications
			for i in p.issues:
				if i.editor is not None:
					f = i.editor
					if f.OnClose( None ):
						f.Destroy()
					else:
						return False
		return True
